package com.openbravo.data.user;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import cn.ekuma.data.dao.I_DataLogic;
import cn.ekuma.data.dao.bean.AppLoger;
import cn.ekuma.data.dao.bean.I_BaseBean;
import cn.ekuma.data.log.DataLogicLoger;
import cn.ekuma.data.ui.android.editor.AndroidEditorRecord;
import cn.ekuma.data.ui.android.editor.DirtyManager;

import com.openbravo.data.basic.BasicException;

public class BrowsableEditableDataModel implements I_AndroidBrowsableEditableData<I_BaseBean>{

    private final static int INX_EOF = -1;

    private BrowsableDataModel m_bd;

    protected List<StateListener> stateListeners=new ArrayList<StateListener>();
    
    protected List<EditorListener> editorListeners=new ArrayList<EditorListener>();
    
    protected List<BrowseListener> browseListeners=new ArrayList<BrowseListener>();

    private AndroidEditorRecord<I_BaseBean> m_editorrecord;
    private DirtyManager m_Dirty;
    private int m_iState; // vinculado siempre al m_editorrecord
//    private DocumentLoader m_keyvalue;
    private int m_iIndex;
    private boolean m_bIsAdjusting;

    private boolean iseditable = true;

    /** Creates a new instance of BrowsableEditableData */
    public BrowsableEditableDataModel(BrowsableDataModel bd, AndroidEditorRecord ed, DirtyManager dirty) {
        m_bd = bd;

        m_editorrecord = ed;
        m_Dirty = dirty;
        m_iState = ST_NORECORD;
        m_iIndex = INX_EOF; // En EOF
        m_bIsAdjusting = false;
//        m_keyvalue = DocumentLoaderBasic.INSTANCE;

        // Inicializo ?
        m_editorrecord.writeValueEOF();
        m_Dirty.setDirty(false);
    }

    public BrowsableEditableDataModel(I_DataLogic dataLogic,Class cl, Comparator c, AndroidEditorRecord ed, DirtyManager dirty,EditorCreator filterCreator) {
        this(new BrowsableDataModel(dataLogic, cl, c , filterCreator), ed, dirty);
    }

    public BrowsableEditableDataModel(I_DataLogic dataLogic,Class cl, Comparator c, AndroidEditorRecord ed, DirtyManager dirty) {
        this(new BrowsableDataModel(dataLogic, cl, c), ed, dirty);
    }

    public BrowsableEditableDataModel(I_DataLogic dataLogic,Class cl, AndroidEditorRecord ed, DirtyManager dirty,EditorCreator filterCreator) {
        this(new BrowsableDataModel(dataLogic, cl, filterCreator), ed, dirty);
    }

    public BrowsableEditableDataModel(I_DataLogic dataLogic,Class cl, AndroidEditorRecord ed, DirtyManager dirty) {
        this(new BrowsableDataModel(dataLogic, cl), ed, dirty);
    }


    public final boolean isAdjusting() {
        return m_bIsAdjusting || m_bd.isAdjusting();
    }

    public final I_BaseBean getCurrentElement() {
        return (m_iIndex >= 0 && m_iIndex < m_bd.getSize()) ? m_bd.getElementAt(m_iIndex) : null;
    }
    public final int getIndex() {
        return m_iIndex;
    }

    public final void addStateListener(StateListener l) {
    	stateListeners.add( l);   
    }
    
    public final void removeStateListener(StateListener l) {
    	stateListeners.remove(l);
    }
    
    public final void addEditorListener(EditorListener l) {
    	editorListeners.add(l);
    }
    
    public final void removeEditorListener(EditorListener l) {
    	editorListeners.remove(l);
    }

    public final void addBrowseListener(BrowseListener l) {
    	browseListeners.add(l);
    }
    public final void removeBrowseListener(BrowseListener l) {
    	browseListeners.remove(l);
    }

    public final void addListDataListener(ListDataListener l) {
        m_bd.addListDataListener(l);
    }

    public final void removeListDataListener(ListDataListener l) {
        m_bd.removeListDataListener(l);
    }

    public int getState() {
        return m_iState;
    }

    private void fireStateUpdate() {
        int iState = getState();
        for (StateListener l:stateListeners) {
            l.updateState(iState);
        }
    }
    protected void fireDataBrowse() {

        m_bIsAdjusting = true;
        // Lanzamos los eventos...
        I_BaseBean obj = getCurrentElement();
        int iIndex = getIndex();
        int iCount = m_bd.getSize();

        // actualizo el registro
        if (obj == null) {
            m_iState = ST_NORECORD;
            m_editorrecord.writeValueEOF();
        } else {
            m_iState = ST_UPDATE;
            m_editorrecord.writeValueEdit(obj);
        }
        m_Dirty.setDirty(false);
        fireStateUpdate();

        // Invoco a los Editor Listener
       
        for (EditorListener l:editorListeners) {
             l.updateValue(obj);
        }
        // Y luego a los Browse Listener
       
        for (BrowseListener l:browseListeners) {
             l.updateIndex(iIndex, iCount);
        }
        m_bIsAdjusting = false;
    }


    public boolean canLoadData() {
        return m_bd.canLoadData();
    }

    public void setEditable(boolean value) {
        iseditable = value;
    }

    public boolean canInsertData() {
        return iseditable && m_bd.canInsertData();
    }

    public boolean canDeleteData() {
        return iseditable && m_bd.canDeleteData();
    }

    public boolean canUpdateData() {
        return iseditable && m_bd.canUpdateData();
    }

    public void refreshCurrent() {
        baseMoveTo(m_iIndex);
    }

    public void refreshData() throws BasicException {
        saveData();
        m_bd.refreshData();
        m_editorrecord.refresh();
        baseMoveTo(0);
    }
    public void loadData() throws BasicException {
        saveData();
        m_bd.loadData();
        m_editorrecord.refresh();
        baseMoveTo(0);
    }
    public void unloadData() throws BasicException {
        saveData();
        m_bd.unloadData();
        m_editorrecord.refresh();
        baseMoveTo(0);
    }

    public void sort(Comparator c) throws BasicException {
        saveData();
        m_bd.sort(c);
        baseMoveTo(0);
    }

    public void moveTo(int i) throws BasicException {
        saveData();
        if (m_iIndex != i) {
            baseMoveTo(i);
        }
    }

    public final void movePrev() throws BasicException {
        saveData();
        if (m_iIndex > 0) {
            baseMoveTo(m_iIndex - 1);
        }
    }
    public final void moveNext() throws BasicException {
        saveData();
        if (m_iIndex < m_bd.getSize() - 1) {
            baseMoveTo(m_iIndex + 1);
        }
    }
    public final void moveFirst() throws BasicException {
        saveData();
        if (m_bd.getSize() > 0) {
            baseMoveTo(0);
        }
    }
    public final void moveLast() throws BasicException {
        saveData();
        if (m_bd.getSize() > 0) {
            baseMoveTo(m_bd.getSize() - 1);
        }
    }
    public final int findNext(Finder f) throws BasicException {
        return m_bd.findNext(m_iIndex, f);
    }

    public void saveData() throws BasicException {
        if (m_Dirty.isDirty()) {
            if (m_iState == ST_UPDATE) {
            	I_BaseBean obj=m_editorrecord.createValue();
                int i = m_bd.updateRecord(m_iIndex, obj);
                m_editorrecord.refresh();
                baseMoveTo(i);
            } else if (m_iState == ST_INSERT) {
            	I_BaseBean obj=m_editorrecord.createValue();
                int i = m_bd.insertRecord(obj);
                m_editorrecord.refresh();
                baseMoveTo(i);
            } else if (m_iState == ST_DELETE) {
            	I_BaseBean obj=this.getCurrentElement();
                int i = m_bd.removeRecord(m_iIndex);
                m_editorrecord.refresh();
                baseMoveTo(i);
            } // queda ST_NORECORD
        }
    }

    /*
     * Metodos publicos finales (algunos protegidos que podrian ser finales
     */

    public final void actionLoad() throws BasicException {
        loadData();
        if (m_bd.getSize() == 0) {
            actionInsert();
        }
    }

    public final void actionInsert() throws BasicException {
        // primero persistimos
        saveData();

        if (canInsertData()) {
            // Y nos ponemos en estado de insert
            m_iState = ST_INSERT;
            m_editorrecord.writeValueInsert(null);
            m_Dirty.setDirty(false);
            fireStateUpdate(); // ?
        }
    }

    public final void actionDelete() throws BasicException {
        if( m_iState != ST_UPDATE){
            refreshCurrent();
            return;
        }

        // primero persistimos
        saveData();

        if (canDeleteData()) {
            // Y nos ponemos en estado de delete
            I_BaseBean obj = getCurrentElement();
            int iIndex = getIndex();
            int iCount = m_bd.getSize();
            if (iIndex >= 0 && iIndex < iCount) {
                m_iState = ST_DELETE;
                m_editorrecord.writeValueDelete(obj);
                m_Dirty.setDirty(true);
                fireStateUpdate(); // ?
            }
        }
    }

    private final void baseMoveTo(int i) {
    // Este senor y el constructor a INX_EOF, son los unicos que tienen potestad de modificar m_iIndex.
        if (i >= 0 && i < m_bd.getSize()) {
            m_iIndex = i;
        } else {
            m_iIndex = INX_EOF;
        }
        fireDataBrowse();
    }

	public void loadData(List<I_BaseBean> datas) throws BasicException {
		// primero persistimos
        saveData();
        m_iState = ST_NORECORD;
        m_Dirty.setDirty(false);
        m_iIndex = INX_EOF;
		m_bd.loadList(datas);
	}
    boolean retTrue;
	public boolean actionClosingForm(Context c) throws BasicException {
        retTrue=true;
		if (m_Dirty.isDirty()) {
            retTrue=false;
			 new  AlertDialog.Builder(c)   
			 .setTitle("修改确认" )
			 .setMessage("当前对象以变修改，保存吗？" )
			 .setPositiveButton("保存" ,  new DialogInterface.OnClickListener(){
				public void onClick(DialogInterface dialog, int which) {
					 try {
						saveData();
                        retTrue=true;
					} catch (BasicException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					 
				}
			 })   
			 .setNegativeButton("不保存" , new DialogInterface.OnClickListener(){
					public void onClick(DialogInterface dialog, int which) {
						 refreshCurrent(); 
					}
			 })   
			 .show();    	
	     }
		return retTrue;
	}

	public void actionReloadCurrent(Context c) {
		if (m_Dirty.isDirty()) {
			 new  AlertDialog.Builder(c)   
			 .setTitle("重新加载" )
			 .setMessage("重新加载当前对象吗？" )
			 .setPositiveButton("是" ,  new DialogInterface.OnClickListener(){
				public void onClick(DialogInterface dialog, int which) {
					 refreshCurrent();
				}
			 })   
			 .setNegativeButton("否" , null)   
			 .show();    	
	     }
		
	}

    @Override
    public int getCount() {
        return m_bd.getSize();
    }

    @Override
    public I_BaseBean getItem(int position) {
        return m_bd.getElementAt(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }
}